﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;

using FineCollection.Intf;

using NUnit.Framework;



namespace FineCollection.Test
{


    public static class AssertExt
    {
        
        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _true_(this bool b)
        {
            Assert.IsTrue(b);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _false_(this bool b)
        {
            Assert.IsFalse(b);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _is_null_(this object obj)
        {
            Assert.IsNull(obj);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _is_not_null_(this object obj)
        {
            Assert.IsNotNull(obj);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _equals_<T>(this T got, T exp)
        {
            Assert.AreEqual(exp, got);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _not_equals_<T>(this T got, T exp)
        {
            Assert.AreNotEqual(exp, got);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _same_<T>(this T got, T exp)
        {
            Assert.AreSame(exp, got);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _array_<T>(this T[] got, params T[] exp)
        {
            Assert.AreEqual(exp, got);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static void _array_<T>(this Array got, params T[] exp)
        {
            int n1 = got != null ? got.Length : 0,
                n2 = exp != null ? exp.Length : 0;

            if (n1 == 0 && n2 == 0)
                return;

            if (n1 != n2)
                Assert.AreEqual(exp, got);

            // ReSharper disable PossibleNullReferenceException
            int b1 = got.GetLowerBound(0);
            for (int i = 0; i < n1; i++)  // n1 == n2
            {
                object v1 = got.GetValue(b1 + i);
                T v2 = exp[i];
                if (!object.Equals(v1, v2))
                {
                    Assert.AreEqual(exp, got);
                    break;
                }
            }
            // ReSharper restore PossibleNullReferenceException
        }


        /*
        public static void _in_<T>(this T value, T min, T max)
            where T: IComparable<T>
        {
            if (value == null)
                Assert.Fail(string.Format("Got null when expected a value form {0}..{1}", min, max));
            if (value.CompareTo(min) == -1)
                Assert.Fail(string.Format("Got too small value {0} when expected a value form {1}..{2}", value, min, max));
            if (value.CompareTo(max) == +1)
                Assert.Fail(string.Format("Got too large value {0} when expected a value form {1}..{2}", value, min, max));
        }
        */ 


        public static void _in_<T>(this T value, RSet<T> set)
        {
            if (set == null)
                throw new ArgumentNullException("set");
            if (set.IsEmpty)
                throw new ArgumentException("Argument set should not be empty.");

            if (!set.Contains(value))
                Assert.Fail(string.Format("Got {0} when expected one of {1}.", value, set));
        }


        public static void _in_<T>(this T value, params T[] exp)
            where T: IComparable<T>
        {
            if (exp == null || exp.Length == 0)
                throw new ArgumentException("At least one possible value should be specified.");

            bool ok;
            if (value == null)
                ok = Array.Exists(exp, x => x == null);
            else
                ok = Array.Exists(exp, x => value.Equals(x));

            if (!ok)
                Assert.Fail(string.Format("Got {0} when expected one of {1}.", value, exp));
        }


        public static void _in_<T>(this T value, IEnumerable<T> items)
            where T: IComparable<T>
        {
            if (items == null)
                throw new ArgumentNullException("items");

            int n = 0;
            foreach (var item in items)
            {
                if (value == null)
                {
                    if (item == null)
                        return;
                }
                else
                {
                    if (value.Equals(item))
                        return;
                }

                n++;
            }

            T[] array = new T[n];
            int i = 0;
            foreach (var item in items) array[i++] = item;

            Assert.Fail(string.Format("Got {0} when expected one of {1}.", value, array));
        }


    }


}